package net.sourceforge.fidocadj.dialogs;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.event.*;
import net.sourceforge.fidocadj.globals.*;
import net.sourceforge.fidocadj.dialogs.mindimdialog.MinimumSizeDialog;
/** The class DialogAttachImage allows to determine which image has to be
attached and shown as a background (for retracing/vectorization purposes).
<pre>
This file is part of FidoCadJ.
FidoCadJ is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FidoCadJ is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FidoCadJ. If not,
@see <a href=http://www.gnu.org/licenses/>http://www.gnu.org/licenses/</a>.
Copyright 2017 by Davide Bucci
</pre>
@author Davide Bucci
*/
public class DialogAttachImage extends MinimumSizeDialog
{
private final JFrame parent; // Parent window
private JTextField fileName; // File name text field
private JTextField resolution; // Resolution text field
private JTextField xcoord; // x coordinate of the left top corner
private JTextField ycoord; // y coordinate of the left top corner
private JTextField xsize; // x size in mm of the image
private JTextField ysize; // y size in mm of the image
private BufferedImage img;
private final int USE_RESOLUTION=0;
private final int USE_SIZE_X=1;
private final int USE_SIZE_Y=2;
private boolean attach; // Indicates that the attach should be done
private boolean showImage;
/** Standard constructor.
@param p the dialog parent
*/
public DialogAttachImage(JFrame p)
{
super(500, 450, p, Globals.messages.getString("Attach_image_t"),
true);
parent=p;
showImage=true;
int ygrid=0;
// Obtain the current content pane and create the grid layout manager
// which will be used for putting the elements of the interface.
GridBagLayout bgl=new GridBagLayout();
GridBagConstraints constraints;
Container contentPane=getContentPane();
contentPane.setLayout(bgl);
JLabel lblfilename=
new JLabel(Globals.messages.getString("Image_file_attach"));
constraints = DialogUtil.createConst(0,ygrid,1,1,100,100,
GridBagConstraints.EAST, GridBagConstraints.NONE,
new Insets(6,6,6,6));
contentPane.add(lblfilename, constraints);
fileName=new JTextField(10);
fileName.setText("");
fileName.getDocument().addDocumentListener(new DocumentListener() {
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void insertUpdate(DocumentEvent e)
{
loadImage();
}
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void removeUpdate(DocumentEvent e)
{
loadImage();
}
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void changedUpdate(DocumentEvent e)
{
loadImage();
}
});
constraints = DialogUtil.createConst(1,ygrid,1,1,100,100,
GridBagConstraints.EAST, GridBagConstraints.BOTH,
new Insets(6,6,6,6));
contentPane.add(fileName, constraints);
JButton browse=new JButton(Globals.messages.getString("Browse"));
constraints = DialogUtil.createConst(2,ygrid++,1,1,100,100,
GridBagConstraints.CENTER, GridBagConstraints.NONE,
new Insets(6,0,12,12));
contentPane.add(browse, constraints);
browse.addActionListener(createBrowseActionListener());
JLabel lblresolution=
new JLabel(Globals.messages.getString("Image_resolution"));
constraints = DialogUtil.createConst(0,ygrid,1,1,100,100,
GridBagConstraints.EAST, GridBagConstraints.NONE,
new Insets(6,6,6,6));
contentPane.add(lblresolution, constraints);
resolution=new JTextField(10);
resolution.setText("200");
// If the user changes the resolution, update the size calculation.
resolution.getDocument().addDocumentListener(new DocumentListener() {
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void insertUpdate(DocumentEvent e)
{
calculateSizeAndResolution(USE_RESOLUTION);
}
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void removeUpdate(DocumentEvent e)
{
calculateSizeAndResolution(USE_RESOLUTION);
}
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void changedUpdate(DocumentEvent e)
{
calculateSizeAndResolution(USE_RESOLUTION);
}
});
constraints = DialogUtil.createConst(1,ygrid++,2,1,100,100,
GridBagConstraints.EAST, GridBagConstraints.BOTH,
new Insets(6,6,6,6));
contentPane.add(resolution, constraints);
JLabel lblsize=
new JLabel(Globals.messages.getString("Image_size_mm"));
constraints = DialogUtil.createConst(0,ygrid,1,1,100,100,
GridBagConstraints.EAST, GridBagConstraints.NONE,
new Insets(6,6,6,6));
contentPane.add(lblsize, constraints);
xsize=new JTextField(5);
xsize.setText("");
xsize.getDocument().addDocumentListener(new DocumentListener() {
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void insertUpdate(DocumentEvent e)
{
calculateSizeAndResolution(USE_SIZE_X);
}
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void removeUpdate(DocumentEvent e)
{
calculateSizeAndResolution(USE_SIZE_X);
}
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void changedUpdate(DocumentEvent e)
{
calculateSizeAndResolution(USE_SIZE_X);
}
});
constraints = DialogUtil.createConst(1,ygrid,1,1,100,100,
GridBagConstraints.EAST, GridBagConstraints.BOTH,
new Insets(6,6,6,6));
contentPane.add(xsize, constraints);
ysize=new JTextField(5);
ysize.setText("");
ysize.getDocument().addDocumentListener(new DocumentListener() {
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void insertUpdate(DocumentEvent e)
{
calculateSizeAndResolution(USE_SIZE_Y);
}
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void removeUpdate(DocumentEvent e)
{
calculateSizeAndResolution(USE_SIZE_Y);
}
/** Needed to implement the DocumentListener interface
@param e the document event.
*/
public void changedUpdate(DocumentEvent e)
{
calculateSizeAndResolution(USE_SIZE_Y);
}
});
constraints = DialogUtil.createConst(2,ygrid++,1,1,100,100,
GridBagConstraints.EAST, GridBagConstraints.BOTH,
new Insets(6,6,6,6));
contentPane.add(ysize, constraints);
JLabel lblcoords=
new JLabel(Globals.messages.getString("Top_left_coords"));
constraints = DialogUtil.createConst(0,ygrid,1,1,100,100,
GridBagConstraints.EAST, GridBagConstraints.NONE,
new Insets(6,6,6,6));
contentPane.add(lblcoords, constraints);
xcoord=new JTextField(5);
xcoord.setText("0");
constraints = DialogUtil.createConst(1,ygrid,1,1,100,100,
GridBagConstraints.EAST, GridBagConstraints.BOTH,
new Insets(6,6,6,6));
contentPane.add(xcoord, constraints);
ycoord=new JTextField(5);
ycoord.setText("0");
constraints = DialogUtil.createConst(2,ygrid++,1,1,100,100,
GridBagConstraints.EAST, GridBagConstraints.BOTH,
new Insets(6,6,6,6));
contentPane.add(ycoord, constraints);
// Put the No image, OK and Cancel buttons and make them active.
JButton noImg=new JButton(Globals.messages.getString("No_img"));
JButton ok=new JButton(Globals.messages.getString("Ok_btn"));
JButton cancel=new JButton(Globals.messages.getString("Cancel_btn"));
Box b=Box.createHorizontalBox();
b.add(Box.createHorizontalGlue());
ok.setPreferredSize(cancel.getPreferredSize());
b.add(noImg);
b.add(Box.createHorizontalStrut(12));
if (Globals.okCancelWinOrder) {
b.add(ok);
b.add(Box.createHorizontalStrut(12));
b.add(cancel);
} else {
b.add(cancel);
b.add(Box.createHorizontalStrut(12));
b.add(ok);
}
constraints = DialogUtil.createConst(1,ygrid++,3,1,0,0,
GridBagConstraints.EAST, GridBagConstraints.NONE,
new Insets(12,40,0,0));
contentPane.add(b, constraints); // Add buttons
noImg.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
attach=true;
showImage=false;
fileName.setText("");
setVisible(false);
}
});
ok.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
if(validateForm()) {
attach=true;
setVisible(false);
}
}
});
cancel.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
setVisible(false);
}
});
// Here is an action in which the dialog is closed
AbstractAction cancelAction = new AbstractAction ()
{
public void actionPerformed (ActionEvent e)
{
setVisible(false);
}
};
DialogUtil.addCancelEscape (this, cancelAction);
pack();
DialogUtil.center(this);
getRootPane().setDefaultButton(ok);
}
private boolean isCalculating;
/** Calculate the relations between size and resolution of the image.
@param useSize if true, calculate resolution from size.
if false, calculate size from resolution.
*/
private void calculateSizeAndResolution(int useSize)
{
if(isCalculating || img==null)
return;
isCalculating=true;
final double oneinch=25.4; // Conversion between inches and mm.
switch (useSize) {
case USE_RESOLUTION:
try {
double res=getResolution();
double w=img.getWidth()/res*oneinch;
double h=img.getHeight()/res*oneinch;
xsize.setText(Globals.roundTo(w,3));
ysize.setText(Globals.roundTo(h,3));
} catch (java.lang.NumberFormatException E){
isCalculating=false;
return;
}
break;
case USE_SIZE_X:
try {
double sizex=getSizeX();
double res=img.getWidth()/sizex*oneinch;
setResolution(res);
double h=img.getHeight()/res*oneinch;
ysize.setText(Globals.roundTo(h,3));
} catch (java.lang.NumberFormatException E){
isCalculating=false;
return;
}
break;
case USE_SIZE_Y:
try {
double sizey=getSizeY();
double res=img.getHeight()/sizey*oneinch;
setResolution(res);
double w=img.getWidth()/res*oneinch;
xsize.setText(Globals.roundTo(w,3));
} catch (java.lang.NumberFormatException E){
isCalculating=false;
return;
}
break;
}
isCalculating=false;
}
/** Create an action listener which handle clicking on the 'browse' button.
@return the ActionListener
*/
private ActionListener createBrowseActionListener()
{
return new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
// Open the browser in order to let the user select the file
// name on which export
if(Globals.useNativeFileDialogs) {
// Native file dialog
FileDialog fd = new FileDialog(parent,
Globals.messages.getString("Select_file_export"),
FileDialog.LOAD);
String filen;
// Set defaults and make visible.
fd.setDirectory(new File(fileName.getText()).getPath());
fd.setVisible(true);
// The user has selected a file.
if(fd.getFile() != null) {
filen=Globals.createCompleteFileName(
fd.getDirectory(),
fd.getFile());
fileName.setText(filen);
}
} else {
// Swing file dialog
JFileChooser fc = new JFileChooser(
new File(fileName.getText()).getPath());
int r = fc.showOpenDialog(null);
if (r == JFileChooser.APPROVE_OPTION) {
fileName.setText(fc.getSelectedFile().toString());
}
}
loadImage();
calculateSizeAndResolution(USE_RESOLUTION);
}
};
}
/** Validate the data entered by the user.
@return true if the data is valid.
*/
private boolean validateForm()
{
try {
img=ImageIO.read(new File(getFilename()));
getResolution();
getSizeX();
getSizeY();
getCornerX();
getCornerY();
} catch (NumberFormatException N) {
JOptionPane.showMessageDialog(parent,
Globals.messages.getString("Format_invalid"),
"",
JOptionPane.INFORMATION_MESSAGE);
return false;
} catch (IOException E) {
JOptionPane.showMessageDialog(parent,
Globals.messages.getString("Can_not_attach_image"),
"",
JOptionPane.INFORMATION_MESSAGE);
return false;
}
return true;
}
/** Load the background image. Or at least try to do it!
*/
private void loadImage()
{
try {
img=ImageIO.read(new File(getFilename()));
} catch (IOException E) {
return;
}
}
/** Indicates that the image attach should be done: the user selected
the "ok" button.
@return a boolean value which indicates if the attach should be done.
*/
public boolean shouldAttach()
{
return attach;
}
/** Get the filename
@return a string containing the file name given by the user.
*/
public String getFilename()
{
return fileName.getText();
}
/** Set the filename
@param s a string containing the file name given by the user.
*/
public void setFilename(String s)
{
fileName.setText(s);
}
/** Get the resolution.
@return the resolution in dpi of the image to be used.
*/
public double getResolution()
{
return Double.parseDouble(resolution.getText());
}
/** Get the width of the image.
@return the width in mm
*/
public double getSizeX()
{
return Double.parseDouble(xsize.getText());
}
/** Get the height of the image.
@return the height in mm
*/
public double getSizeY()
{
return Double.parseDouble(ysize.getText());
}
/** Set the resolution
@param r the resolution in dpi of the image to be used.
*/
public void setResolution(double r)
{
resolution.setText(Globals.roundTo(r));
}
/** Set the coordinates of the left topmost point of the image (use
FidoCadJ coordinates).
@param x the x coordinate.
@param y the y coordinate.
*/
public void setCorner(double x, double y)
{
xcoord.setText(Globals.roundTo(x,3));
ycoord.setText(Globals.roundTo(y,3));
}
/** Get the x coordinate of the left topmost point of the image (use
FidoCadJ coordinates).
@return the x coordinate.
*/
public double getCornerX()
{
return Double.parseDouble(xcoord.getText());
}
/** Check if the image has to be shown or not.
@return true if the image attached has to be shown.
*/
public boolean getShowImage()
{
return showImage;
}
/** Get the currently loaded image.
@return the image.
*/
public BufferedImage getImage()
{
return img;
}
/** Get the y coordinate of the left topmost point of the image (use
FidoCadJ coordinates).
@return the y coordinate.
*/
public double getCornerY()
{
return Double.parseDouble(ycoord.getText());
}
}